package org.example.shop.shiro;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.User;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
import org.example.shop.vo.ApiResponse;
import org.springframework.util.StringUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.file.AccessDeniedException;
import java.time.LocalDateTime;
import java.util.Date;

/**
 * 用户请求过滤器
 */
@Slf4j
public class UserAuthFilter extends BasicHttpAuthenticationFilter {
    /**
     * 1.判断是否允许通过
     *
     * @param request
     * @param response
     * @param mappedValue
     * @return
     */
    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        log.info("判断是否允许通过");
        LocalDateTime dateTime = LocalDateTime.now();
        int hour = dateTime.getHour();
        if(hour < 8 || hour >= 21){
            throw new AuthenticationException("超出了访问时间");
        }
        try {
            return executeLogin(request, response);
        } catch (Exception e) {
            e.printStackTrace();
//            responseError(response, ApiResponse.error(401,"shiro进行登录异常了"));
            return false; // 只要时false 则表示不允许通过
        }
    }

    @Override
    protected boolean isLoginAttempt(ServletRequest request, ServletResponse response) {
        log.info("是否进行登录请求");
        String token = ((HttpServletRequest) request).getHeader("token");
        if (token != null) {
            return true;
        }
        return false;
    }

    /**
     * 根据head 创建鉴权使用的token
     *
     * @param request
     * @param response
     * @return
     */
    @Override
    protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {
        // 从请求头中获取token
        String tokenValue = ((HttpServletRequest) request).getHeader("token");
        log.info("正在获取token {}",tokenValue);
        if (StringUtils.isEmpty(tokenValue)) {
            return null;
        }
        // 获取接口上传的token 并进行初始化
        UserToken token = new UserToken();
        token.setToken(tokenValue);
        return token;
    }
    /**
     * shiro验证成功调用
     *
     * @param token
     * @param subject
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @Override
    protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception {
        UserToken t = (UserToken)token;
        log.info("验证登录成功..." + t.getToken());
        // 此处开始验证token的有效性
        // 不通过则返回 false
        return true;//
    }

    // 不允许通过 会默认回调该方法
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        responseError(response, ApiResponse.error(403,"鉴权失败 不允许访问"));
        return false;
    }

    // 鉴权失败后的错误响应
    private void responseError(ServletResponse response, Object msg) {
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        httpResponse.setStatus(401);
        httpResponse.setCharacterEncoding("UTF-8");
        httpResponse.setContentType("application/json;charset=UTF-8");
        try {
            String rj = new ObjectMapper().writeValueAsString(msg);
            httpResponse.getWriter().append(rj);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
